package frontend.pages.admin.team;

import backend.model.admin.Employee;
import backend.model.admin.Foreman;
import backend.model.admin.Team;
import backend.service.admin.EmployeeService;
import backend.service.admin.ForemanService;
import backend.service.admin.TeamService;
import frontend.components.base.PaletteComponent;
import frontend.core.TimeTrackingWebApplication;
import frontend.model.admin.TeamUIModel;
import frontend.pages.admin.base.AbstractManagingForm;
import frontend.components.base.ComponentFactory;
import frontend.components.other.DBModelChoiceRenderer;
import org.apache.log4j.Logger;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.validation.ValidationError;

import java.util.*;

public class TeamForm extends AbstractManagingForm<TeamUIModel> {

    private static Logger logger = Logger.getLogger(TeamForm.class);

    private static final int DEFAULT_TEAM_ID = 1;

    private static final String RESOURCE_KEY_FIELD_LABEL_NAME = "pages.admin.team.form.name";
    private static final String RESOURCE_KEY_FIELD_LABEL_FOREMAN = "pages.admin.team.form.foreman";
    private static final String RESOURCE_KEY_FIELD_LABEL_IS_EXTERNAL = "pages.admin.team.form.isExternal";
    private static final String RESOURCE_KEY_FIELD_LABEL_IS_ACTIVE = "pages.admin.team.form.isActive";

    private static final String RESOURCE_KEY_VALIDATION_SAME_TEAM_NAME = "validation.form.team.sameTeamName";
    private static final String RESOURCE_KEY_VALIDATION_CANNOT_DELETE_DEFAULT_TEAM = "validation.form.team.cannotDeleteDefaultTeam";
    private static final String RESOURCE_KEY_VALIDATION_DEFAULT_TEAM_ALWAYS_ACTIVE = "validation.form.team.defaultTeamAlwaysActive";

    private PaletteComponent employeesComponent;

	public TeamForm(String id, TeamUIModel teamUIModel) {
		super(id, teamUIModel);		
	}

	@Override
	protected void constructFormContent() {
		WebMarkupContainer nameComponent = ComponentFactory.createTextFieldComponent("name", RESOURCE_KEY_FIELD_LABEL_NAME, uiModel);
        WebMarkupContainer isExternalComponent = ComponentFactory.createCheckboxComponent("isExternal", RESOURCE_KEY_FIELD_LABEL_IS_EXTERNAL, uiModel);
        WebMarkupContainer isActiveComponent = ComponentFactory.createCheckboxComponent("isActive", RESOURCE_KEY_FIELD_LABEL_IS_ACTIVE, uiModel);
        WebMarkupContainer foremanComponent = ComponentFactory.createDropDownChoiceComponent("foreman", RESOURCE_KEY_FIELD_LABEL_FOREMAN, uiModel,
                getAvailableForemen(), new DBModelChoiceRenderer<Foreman>(), false);
        employeesComponent = ComponentFactory.createPaletteComponent("employees", uiModel, getAvailableEmployees(), 10, false);
		add(nameComponent, isExternalComponent, isActiveComponent, foremanComponent, employeesComponent);
	}

    @Override
    protected Class getResponsePage() {
        return TeamManagingPage.class;
    }

    @Override
    protected void doFormValidation() {
        validateNotEmpty(uiModel.getName(), RESOURCE_KEY_FIELD_LABEL_NAME);
        validateNotEmpty(uiModel.getForeman(), RESOURCE_KEY_FIELD_LABEL_FOREMAN);
        if (isActiveWasChanged() && uiModel.getDBModel().getId() == 1) {
            addFieldValidationError(RESOURCE_KEY_FIELD_LABEL_IS_ACTIVE, RESOURCE_KEY_VALIDATION_DEFAULT_TEAM_ALWAYS_ACTIVE);
        }
        if ((uiModel.getName() != null) && nameWasChanged()) {
            TeamService service =  TimeTrackingWebApplication.getService(TeamService.class);
            if (service.findTeamByName(uiModel.getName()) != null) {
                addFieldValidationError(RESOURCE_KEY_FIELD_LABEL_NAME, RESOURCE_KEY_VALIDATION_SAME_TEAM_NAME);
            }
        }
    }

    private boolean nameWasChanged() {
        return (false == uiModel.getName().equals(uiModel.getDBModel().getName()));
    }

    private boolean isActiveWasChanged() {
        return uiModel.getIsActive() != uiModel.getDBModel().getIsActive();
    }

    private List<Foreman> getAvailableForemen() {
        List<Foreman> availableForemen = new ArrayList<Foreman>();
        availableForemen.addAll(TimeTrackingWebApplication.getService(ForemanService.class).findAllActiveForemen());
        return availableForemen;
    }

    protected boolean delete() {
        if (uiModel.getDBModel().getId() == 1) {
            ValidationError validationError = createValidationError(RESOURCE_KEY_VALIDATION_CANNOT_DELETE_DEFAULT_TEAM);
            error(validationError.getMessage());
            return false;
        }
        return super.delete();
    }

    protected void postSave(AjaxRequestTarget target) {
        if (uiModel.getDBModel().getId() != 1) {
            TeamService teamService = TimeTrackingWebApplication.getService(TeamService.class);
            EmployeeService employeeService = TimeTrackingWebApplication.getService(EmployeeService.class);
            Team defaultTeam = teamService.findDefaultTeam();
            Iterator<Employee> unselectedEmployees = employeesComponent.getUnselectedChoices();
            while (unselectedEmployees.hasNext()) {
                Employee employee = unselectedEmployees.next();
                // previous in the team, but now removed from this team -> should go to default team
                if (employee.getTeam() != null && employee.getTeam().getId() == uiModel.getDBModel().getId()) {
                    employee.setTeam(defaultTeam);
                    logger.info("Saving entity: [" + employee.getClass() + "] - " + employee.getDisplayLabel());
                    employeeService.saveDBModel(employee);
                }
            }
        }
        super.postSave(target);
    }

    private List<Employee> getAvailableEmployees() {
        List<Employee> employeesWithNoTeam = TimeTrackingWebApplication.getService(EmployeeService.class).findAllActiveEmployeesByTeam(DEFAULT_TEAM_ID);
        List<Employee> employeesOfCurrentTeam = TimeTrackingWebApplication.getService(EmployeeService.class).findAllActiveEmployeesByTeam(uiModel.getDBModel().getId());

        List<Employee> availableEmployees = new LinkedList<Employee>();
        availableEmployees.addAll(employeesWithNoTeam);
        availableEmployees.addAll(employeesOfCurrentTeam);
        return availableEmployees;
    }
}
